using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Windows.Forms;
using DirkRettschlag.Utils;

namespace Departure
{
    class BuildDataThread
    {
        ContainerControl sender = null;

        Delegate senderDelegate = null;

        string source = "";

        StationSettings stationSettings;
        GeneralSettings generalSettings;

        public BuildDataThread(ContainerControl sender, Delegate senderDelegate, string Source, StationSettings stationSettings, GeneralSettings generalSettings)
		{
			this.sender = sender;
			this.senderDelegate = senderDelegate;
            this.source = Source;
            this.stationSettings = stationSettings;
            this.generalSettings = generalSettings;

		}

		/// <summary>
		/// Method for ThreadStart delegate
		/// </summary>
		public void RunProcess()
		{
			Thread.CurrentThread.IsBackground = true; //make them a daemon
			LocalRunProcess();
		}

		/// <summary>
		/// Local Method for the actual work.
		/// </summary>
        private void LocalRunProcess()
        {
            if (generalSettings.UseWAP)
            {
                GetTrainsWAP();
            }
            else
            {
                GetTrainsHTML();
            }
        }

        private void GetTrainsWAP()
        {
            try
            {
                string Time;
                string Train;
                string Direction;
                string Platform;
                string Later;
                string FullDateTime;

                int currentItem = 0;
                int allItems = 0;

                this.source = Utilities.ClearText(this.source);

                if (this.source.IndexOf("realtime information") >= 0 || this.source.IndexOf("Real-time information") >= 0)
                {

                    Regex regex = new Regex("---<br/>.*?<br/>.*?<br/>", RegexOptions.Singleline | RegexOptions.IgnoreCase);

                    MatchCollection matchcollection = regex.Matches(this.source);

                    allItems = matchcollection.Count;

                    foreach (Match tmpmatch in matchcollection)
                    {
                        currentItem++;

                        this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", false, false, true, currentItem, allItems });

                        regex = new Regex("<{0,1}.b>", RegexOptions.Singleline | RegexOptions.IgnoreCase);

                        string[] matchcollection2 = regex.Split(tmpmatch.Value);

                        if (matchcollection2.Length == 5)
                        {
                            Time = ClearTime(Regex.Replace(matchcollection2[3], "<.*?>", "")).Trim();
                            Train = ClearTrain(Regex.Replace(matchcollection2[1], "<.*?>", "")).Trim();
                            Direction = ClearDirection(Regex.Replace(matchcollection2[2], "<.*?>", "")).Trim();
                            Platform = Regex.Replace(ClearPlatform(GetPlatformWAP(matchcollection2[4])), "<.*?>", "").Trim();
                            Later = ClearLater(Regex.Replace(GetLaterWAP(matchcollection2[4]), "<.*?>", "")).Trim();

                            DateTime FullDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(Time.Split(':')[0]), int.Parse(Time.Split(':')[1]), 0);

                            if (FullDate < DateTime.Now)
                                FullDate = FullDate.AddDays(1);

                            FullDateTime = FullDate.ToFileTimeUtc().ToString();

                            if (FilterData(Train, Direction, Platform))
                            {
                                this.sender.BeginInvoke(this.senderDelegate, new object[] { Time, Train, Direction, Platform, Later, FullDateTime, "", false, false, false, 0, 0});
                            }
                        }
                    }
                }
                else
                {
                    this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "No departures found", true, false, false, 0, 0 });
                }

                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", false, true, false, 0, 0 });
            }
            catch (Exception ex)
            {
                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", ex.Message, true, false, 0, 0 });
            }
        }

        private void GetTrainsHTML()
        {
            try
            {

                string Time;
                string Train;
                string Direction;
                string Platform;
                string Later;
                string FullDateTime;

                int currentItem = 0;
                int allItems = 0;
                                
                if (this.source.IndexOf("Departures valid on") >= 0)
                {
                    Regex regexCountColumns = new Regex("<th class=\"resultdark.*?>.+?</th>", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled);

                    int countColumns = regexCountColumns.Matches(this.source).Count;

                    Regex regex;
                    if (countColumns == 3)
                    {
                        regex = new Regex("<tr.*?>.*?<td.*?>.*?<span.*?>(?<Time>.*?)</span>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Train>.*?)</a>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Direction>.*?)</a>.*?</td>.*?</tr>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else if (countColumns == 4)
                    {
                        regex = new Regex("<tr.*?>.*?<td.*?>.*?<span.*?>(?<Time>.*?)</span>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Train>.*?)</a>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Direction>.*?)</a>.*?</td>.*?<td.*?></td>.*?<td.*?>(?<Platform>.*?)</td>.*?</tr>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else if (countColumns == 5)
                    {
                        regex = new Regex("<tr.*?>.*?<td.*?>.*?<span.*?>(?<Time>.*?)</span>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Train>.*?)</a>.*?</td>.*?<td.*?>.*?<a href.*?>(?<Direction>.*?)</a>.*?</td>.*?<td.*?></td>.*?<td.*?>(?<Platform>.*?)</td>.*?<td.*?></td>.*?<td.*?>.*?<span.*?><span.*?>(?<Later>.*?)</span>.*?</td>.*?</tr>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    }
                    else
                    {
                        throw new Exception("Source not valid.");
                    }

                    this.source = Regex.Replace(this.source, "^.*?Time&nbsp;</th>", "", RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                    this.source = Regex.Replace(this.source, "</table>.*", "", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);

                    Debug.WriteLine(DateTime.Now.ToString());
                    MatchCollection matchcollection = regex.Matches(this.source);

                    Debug.WriteLine(DateTime.Now.ToString());
                    allItems = Regex.Matches(this.source, "<tr.*?>.*?</tr>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled).Count;

                    Debug.WriteLine(DateTime.Now.ToString());
                    if (allItems > 0)
                    {
                        
                        Debug.WriteLine(DateTime.Now.ToString());
                        foreach (Match tmpmatch in matchcollection)
                        {
                            currentItem++;

                            this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", false, false, true, currentItem, allItems });

                            Time = ClearTime(Utilities.ClearText(tmpmatch.Groups["Time"].Value)).Trim();
                            Train = ClearTrain(Utilities.ClearText(tmpmatch.Groups["Train"].Value)).Trim();
                            Direction = Utilities.ClearText(tmpmatch.Groups["Direction"].Value).Trim();
                            
                            if (tmpmatch.Groups.Count >= 5 )
                                Platform = ClearPlatform(Utilities.ClearText(tmpmatch.Groups["Platform"].Value)).Trim();
                            else
                                Platform = "";
                            if (tmpmatch.Groups.Count >= 6)
                                Later = ClearLater(Utilities.ClearText(tmpmatch.Groups["Later"].Value)).Trim();
                            else
                                Later = "";

                            if (FilterData( Train, Direction, Platform))
                            {
                                DateTime FullDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(Time.Split(':')[0]), int.Parse(Time.Split(':')[1]), 0);

                                if (FullDate < DateTime.Now.AddMinutes(-2))
                                    FullDate = FullDate.AddDays(1);

                                FullDateTime = FullDate.ToFileTimeUtc().ToString();

                                this.sender.BeginInvoke(this.senderDelegate, new object[] { Time, Train, Direction, Platform, Later, FullDateTime, "", false, false, false, 0, 0 });
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("No departures found.");
                    }
                }
                else
                {
                    throw new Exception("No departures found.");
                }

                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", "", false, true, false, 0, 0 });
            }
            catch (Exception ex)
            {
                this.sender.BeginInvoke(this.senderDelegate, new object[] { "", "", "", "", "", "", ex.Message, true, false, false, 0, 0 });
            }
        }


        private bool FilterData(string Train, string Direction, string Platform)
        {
            Regex regex;

            bool filterhitTrain = false;
            bool filterhitDirection = false;
            bool filterhitPlatform = false;
            
            // Bus Filter
            regex = new Regex("^Bus", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            if (this.stationSettings.TransfersSelected[7].ToString() == "0" && regex.Match(Train).Success)
                return false;
            // IRE Filter
            regex = new Regex("^IRE", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            if (this.stationSettings.TransfersSelected[3].ToString() == "0" && regex.Match(Train).Success)
                return false;
            // RE Filter
            regex = new Regex("^RE", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            if (this.stationSettings.TransfersSelected[4].ToString() == "0" && regex.Match(Train).Success)
                return false;
            // RB Filter
            regex = new Regex("^RB", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
            if (this.stationSettings.TransfersSelected[5].ToString() == "0" && regex.Match(Train).Success)
                return false;

            // Train Filter
            if (this.stationSettings.UseTrainsFilter)
            {
                regex = new Regex(this.stationSettings.TrainsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                if (regex.Match(Train).Success)
                {
                    filterhitTrain = true;
                }
            }

            // Direction Filter
            if (this.stationSettings.UseDirectionsFilter)
            {
                regex = new Regex(this.stationSettings.DirectionsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                if (regex.Match(Direction).Success)
                {
                    filterhitDirection = true;
                }
            }

            // Platform Filter
            if (this.stationSettings.UsePlatformsFilter)
            {
                regex = new Regex(this.stationSettings.PlatformsFilter.Replace(";", "|"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
                if (regex.Match(Platform).Success)
                {
                    filterhitPlatform = true;
                }
            }

            if (this.stationSettings.UseAndFilter)
            {
                if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == false)
                    return filterhitTrain;
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == true && this.stationSettings.UsePlatformsFilter == false)
                    return (filterhitTrain && filterhitDirection);
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == true && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain && filterhitDirection && filterhitPlatform);
                else if (this.stationSettings.UseTrainsFilter == true && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain && filterhitPlatform);
                else if (this.stationSettings.UseTrainsFilter == false && this.stationSettings.UseDirectionsFilter == false && this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitPlatform);
                else //if (this.stationSettings.useTrainsFilter == false && this.stationSettings.useDirectionsFilter == true && this.stationSettings.usePlatformsFilter == false)
                    return (filterhitDirection);
            }
            else
                if (this.stationSettings.UseTrainsFilter == true || this.stationSettings.UseDirectionsFilter == true || this.stationSettings.UsePlatformsFilter == true)
                    return (filterhitTrain || filterhitDirection || filterhitPlatform);
                else
                    return true;
        }

        private string ClearLater(string input)
        {
            input = input.Replace("on time", "");
            input = input.Replace("-", "");
            input = input.Replace("n.a.", "");


            return input;
        }

        private string ClearPlatform(string input)
        {
            input = Regex.Replace(input, "<br>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);

            input = input.Replace("Platf.", "");

            return input;
        }

        private string ClearTime(string input)
        {
            input = input.Replace(" ", "");

            return input;
        }

        private string ClearDirection(string input)
        {
            input = input.Replace("<", "");
            input = input.Replace(">", "");

            return input;
        }

        private string ClearTrain(string input)
        {
            input = input.Replace("S     ", "");
            input = input.Replace("S    ", "");

            input = input.Replace("U     ", "");
            input = input.Replace("U    ", "");

            input = input.Replace(" ", "");

            return input;
        }

        private string GetPlatformWAP(string input)
        {
            string[] output = Regex.Split(input,"&nbsp;&nbsp;");

            if (output.Length == 3)
                return output[2];
            else
                return "";
        }

        private string GetLaterWAP(string input)
        {
            string[] output = Regex.Split(input, "&nbsp;&nbsp;");
            if (output.Length > 1)
                return output[1];
            else
                return "";
        }

    }
}
